using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;


namespace ADModify.Library
{
	/// <summary>
	/// LogFile class contains 3 methods:  LogSuccess, LogFailure, and ShowResults.
	/// Logs all change attempts to an XML file named after current date/time.  
	/// </summary>
	
	public class LogFile
	{

		//counters for users, successes, failures, and non-changes
		public static int userCount = 0; 
		public static int successCount = 0;
		public static int failureCount = 0;
		public static int nonchangeCount = 0;


		/// <summary>
		/// Logfile::LogSuccess
		/// 
		/// Accepts:
		///		logWriter - Handle to XmlWriter object for logging
		///		UserDN - bind path to the user being modified
		///		attribute - attribute that is being modified
		///		oldValue - previous attributes value
		///		newValue - new value
		///		
		///	Returns:
		///		none
		///		
		///	Writes successful changes to the log file.  
		/// </summary>

		public void LogSuccess(XmlWriter logWriter, string UserDN, string attribute, string oldValue, string newValue)
		{
			
			
			//trim off servername if it was passed.  We don't want to log the servername in the log because this
			//messes up the undo functionality.
			UserDN = UserDN.Replace("LDAP://","");
			string[] UserDNArray = UserDN.Split('/');	
			
			if(UserDNArray.GetUpperBound(0)==0)	//if the array's size is 0, then its just dn (no servername), dn does not contain a forward slash
			{
				UserDN = "LDAP://" + UserDNArray[0];
			}
			else	//array is larger than 0, meaning we have a servername, a dn with a /, or both.
			{
				UserDN = "LDAP://";
				
				for(int j = 0; j <= UserDNArray.GetUpperBound(0); j++)
				{
					//make sure what we're adding back is not a servername on the first pass
					if(j==0)
					{
						if(UserDNArray[j].StartsWith("CN=") || UserDNArray[j].StartsWith("OU="))
						{
							UserDN = UserDN + UserDNArray[j];
						}
					}
					else
					{
						UserDN = UserDN + "/" + UserDNArray[j];
					}
				}
			}
			//remove the third / that results from removing the servername in the above code
			if(UserDN.StartsWith("LDAP:///"))
			{
				UserDN = UserDN.Replace("LDAP:///", "LDAP://");
			}
		
			string type;
			if(oldValue==newValue)
			{
				type = "Already Set to Specified Value";
			}
			else
			{
				type = "Success";
			}

			
			logWriter.WriteStartElement("user");
			logWriter.WriteAttributeString("UserDN", UserDN);
			logWriter.WriteAttributeString("type", type);
			logWriter.WriteAttributeString("attribute", attribute);
			logWriter.WriteAttributeString("oldValue", oldValue);
			logWriter.WriteAttributeString("newValue", newValue);
			logWriter.WriteEndElement();

			//finally
			userCount++;

			if(oldValue == newValue)
			{
				nonchangeCount++;
			}
			else
			{
				successCount++;
			}
		}
		







		/// <summary>
		/// Logfile::LogFailure
		/// 
		/// Accepts:
		///		logWriter - Handle to XmlWriter object for logging
		///		UserDN - bind path to the user being modified
		///		attribute - attribute that is being modified
		///		FailureMessage - The error returned from System.Exception
		///		
		///	Returns:
		///		none
		///		
		///	Logs Failed write attempts along with the error code that was returned from the catch handler.
		/// </summary>
	
		public void LogFailure(XmlWriter logWriter, string UserDN, string attribute, string FailureMessage)
		{


			//trim off servername if it was passed.  We don't want to log the servername in the log because this
			//messes up the undo functionality.
			UserDN = UserDN.Replace("LDAP://","");
			string[] UserDNArray = UserDN.Split('/');	
			
			if(UserDNArray.GetUpperBound(0)==0)	//if the array's size is 0, then its just dn (no servername), dn does not contain a forward slash
			{
				UserDN = "LDAP://" + UserDNArray[0];
			}
			else	//array is larger than 0, meaning we have a servername, a dn with a /, or both.
			{
				UserDN = "LDAP://";
				
				for(int j = 0; j <= UserDNArray.GetUpperBound(0); j++)
				{
					//make sure what we're adding back is not a servername on the first pass
					if(j==0)
					{
						if(UserDNArray[j].StartsWith("CN=") || UserDNArray[j].StartsWith("OU="))
						{
							UserDN = UserDN + UserDNArray[j];
						}
					}
					else
					{
						UserDN = UserDN + "/" + UserDNArray[j];
					}
				}
			}
			//remove the third / that results from removing the servername in the above code
			if(UserDN.StartsWith("LDAP:///"))
			{
				UserDN = UserDN.Replace("LDAP:///", "LDAP://");
			}

			logWriter.WriteStartElement("user");
			logWriter.WriteAttributeString("UserDN", UserDN);
			logWriter.WriteAttributeString("type", "Failure");
			logWriter.WriteAttributeString("attribute", attribute);
			logWriter.WriteAttributeString("message", FailureMessage);
			logWriter.WriteEndElement();


			userCount++;
			failureCount++;
		
		}


		
		/// <summary>
		///Logfile::DumpMailboxRights
		///
		///Accepts:
		///		handle to XmlWriter
		///
		///Returns:
		///		none
		///		
		///Dumps Mailbox Rights data to an XML file
		///

		public void DumpMailboxRights(XmlWriter DumpWriter, string UserDN, string[] MailboxRightsArrayInherited, string[] MailboxRightsArrayNonInherited)
		{

//			//trim off servername if it was passed.  We don't want to log the servername in the log because this
//			//messes up the undo functionality.
//			UserDN = UserDN.Replace("LDAP://","");
//			string[] UserDNArray = UserDN.Split('/');	
//			
//			if(UserDNArray.Length==1)
//			{
//				UserDN = "LDAP://" + UserDNArray[0];
//			}
//			else
//			{
//				UserDN = "LDAP://" + UserDNArray[1];
//			}

			//trim off servername if it was passed.  We don't want to log the servername in the log because this
			//messes up the undo functionality.
			UserDN = UserDN.Replace("LDAP://","");
			string[] UserDNArray = UserDN.Split('/');	
			
			if(UserDNArray.GetUpperBound(0)==0)	//if the array's size is 0, then its just dn (no servername), dn does not contain a forward slash
			{
				UserDN = "LDAP://" + UserDNArray[0];
			}
			else	//array is larger than 0, meaning we have a servername, a dn with a /, or both.
			{
				UserDN = "LDAP://";
				
				for(int j = 0; j <= UserDNArray.GetUpperBound(0); j++)
				{
					//make sure what we're adding back is not a servername on the first pass
					if(j==0)
					{
						if(UserDNArray[j].StartsWith("CN=") || UserDNArray[j].StartsWith("OU="))
						{
							UserDN = UserDN + UserDNArray[j];
						}
					}
					else
					{
						UserDN = UserDN + "/" + UserDNArray[j];
					}
				}
			}
			//remove the third / that results from removing the servername in the above code
			if(UserDN.StartsWith("LDAP:///"))
			{
				UserDN = UserDN.Replace("LDAP:///", "LDAP://");
			}


			DumpWriter.WriteStartElement("user");
			DumpWriter.WriteAttributeString("UserDN", UserDN);

			string Trustee;
			string[] InheritedMailboxRightsSplit;
			string InheritedMailboxRightsMerged = "";

			DumpWriter.WriteStartElement("Inherited");
			
			for(int i=0;i<=MailboxRightsArrayInherited.GetUpperBound(0);i++)
			{
				InheritedMailboxRightsSplit = MailboxRightsArrayInherited[i].Split(',');
				Trustee = InheritedMailboxRightsSplit[0];
				for(int j=1; j<=InheritedMailboxRightsSplit.GetUpperBound(0);j++)
				{
					InheritedMailboxRightsMerged = InheritedMailboxRightsMerged + InheritedMailboxRightsSplit[j].ToString();
				}

				DumpWriter.WriteStartElement("Entry");
				DumpWriter.WriteAttributeString("Trustee", Trustee);
				DumpWriter.WriteAttributeString("Mask", InheritedMailboxRightsMerged);
				DumpWriter.WriteEndElement();
				InheritedMailboxRightsMerged = "";
			}
			DumpWriter.WriteEndElement();
			Trustee = "";

			DumpWriter.WriteStartElement("NotInherited");
			string[] NotInheritedMailboxRightsSplit;
			string NotInheritedMailboxRightsMerged = "";
			for(int i=0;i<=MailboxRightsArrayNonInherited.GetUpperBound(0);i++)
			{
				NotInheritedMailboxRightsSplit = MailboxRightsArrayNonInherited[i].Split(',');
				Trustee = NotInheritedMailboxRightsSplit[0];
				for(int j=1; j<=NotInheritedMailboxRightsSplit.GetUpperBound(0);j++)
				{
					NotInheritedMailboxRightsMerged = NotInheritedMailboxRightsMerged + NotInheritedMailboxRightsSplit[j].ToString();
				}

				DumpWriter.WriteStartElement("Entry");
				DumpWriter.WriteAttributeString("Trustee", Trustee);
				DumpWriter.WriteAttributeString("Mask", NotInheritedMailboxRightsMerged);
				DumpWriter.WriteEndElement();
				NotInheritedMailboxRightsMerged = "";
			}
			DumpWriter.WriteEndElement();
			DumpWriter.WriteEndElement();
			Trustee = "";
		}



		/// <summary>
		/// Logfile::ShowResults
		/// 
		/// Accepts:
		///		none
		///		
		///	Returns:
		///		none
		///		
		///	Writes a brief summary of the changes to the console
		/// </summary>

		public void showResults()
		{
			Console.WriteLine("Successful changes: {0}", successCount);
			Console.WriteLine("Already set to specified value: {0}", nonchangeCount);
			Console.WriteLine("Failed changes: {0}", failureCount);
			Console.WriteLine("");
		}


		///
		///	Logfile::ReturnResults
		///	
		///	Accepts:
		///		none
		///		
		///	Returns:
		///		Results	
		///		
		///	Same thing as showresults, except we return a string array with the change information.
		///
		public string ReturnResults()
		{
			string Results = successCount + "," + nonchangeCount + "," + failureCount;
			return Results;
		}
		#region IDisposable Members

		public void Dispose()
		{
			// TODO:  Add LogFile.Dispose implementation
		}

		#endregion
	}
}
